import com.android.build.api.transform.QualifiedContent
import com.android.build.api.transform.Transform
import com.android.build.api.transform.TransformException
import com.android.build.api.transform.TransformInvocation
import com.android.build.gradle.internal.pipeline.TransformManager

/**
 * Google 官方在 Android Gradle V1.5.0 版本以后提供了 Transfrom API, 允许第三方 Plugin 在打包成 .dex 文件之前的编译过程中操作 .class 文件，
 * 我们需要做的就是实现 Transform 来对 .class 文件遍历以拿到所有方法，修改完成后再对原文件进行替换即可。
 * 总的来说，Gradle Transform 的功能就是把输入的 .class 文件转换为目标字节码文件。
 *
 */
class CustomTransform extends Transform{

    //返回对应的 Task 名称。
    @Override
    String getName() {
        return "MyTransform"
    }

    /*
        确定对那些类型的结果进行转换。
        目前 ContentType 有六种枚举类型，通常我们使用比较频繁的有前两种:
        1、CONTENT_CLASS：表示需要处理 java 的 class 文件。
        2、CONTENT_JARS：表示需要处理 java 的 class 与 资源文件。
        3、CONTENT_RESOURCES：表示需要处理 java 的资源文件。
        4、CONTENT_NATIVE_LIBS：表示需要处理 native 库的代码。
        5、CONTENT_DEX：表示需要处理 DEX 文件。6、CONTENT_DEX_WITH_RESOURCES：表示需要处理 DEX 与 java 的资源文件。
     */
    @Override
    Set<QualifiedContent.ContentType> getInputTypes() {
        return TransformManager.CONTENT_CLASS
    }

    /*
        指定插件的适用范围。
        1、PROJECT：只有项目内容。
        2、SUB_PROJECTS：只有子项目。
        3、EXTERNAL_LIBRARIES：只有外部库，
        4、TESTED_CODE：由当前变体（包括依赖项）所测试的代码。
        5、PROVIDED_ONLY：只提供本地或远程依赖项。
        此外，还有一些复合类型，它们是都是由这五种基本类型组成，以实现灵活确定自定义插件的范围，这里通常是指定整个 project，也可以指定其它范围
     */
    @Override
    Set<? super QualifiedContent.Scope> getScopes() {
        // 适用范围：通常是指定整个 project，也可以指定其它范围
        return TransformManager.SCOPE_FULL_PROJECT
    }

    /*
        表示是否支持增量更新。
        如果返回 true，TransformInput 会包含一份修改的文件列表，如果返回 false，则会进行全量编译，并且会删除上一次的输出内容。
     */
    @Override
    boolean isIncremental() {
        return false
    }

    @Override
    void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
        super.transform(transformInvocation)

        def inputs = transformInvocation.inputs
        def outputProvider = transformInvocation.outputProvider
        //删除之前的输出
        if (outputProvider!=null){
            outputProvider.deleteAll()

            // Transform 的 inputs 有两种类型，一种是目录，一种是 jar，要分开遍历
            inputs.each {input ->
                //（本地 project 编译成的多个 class ⽂件存放的目录）
                input.directoryInputs.each {
                    println it.name
                }
                //（各个依赖所编译成的 jar 文件）
                input.jarInputs.each {
                    println it.name
                }
            }
        }

    }
}